/** 路径处理相关函数
 * @file path.hpp
 * @author Kiven Lee
 * @version 1.0
 * @date 2021-11-16
 *
 * @copyright Kivensoft (c) 2018 - 2021
 *
 */

#pragma once

#include <winsock2.h>
#include <windows.h>
#include <string_view>

#include "../klib/utils.hpp"

namespace kwin {
    /** 获取应用程序全路径名
     *
     * @param out 输出对象
     * @return 程序名长度
     */
    static inline size_t getAppName(klib::dstring_t<256>& out) {
        size_t size;
        // 获取应用程序全路径名，如果返回长度等于缓冲区长度，表示当前缓冲区不足，需要重新分配
        while ((size = ::GetModuleFileNameA(NULL, out.data(), out.size())) == out.size())
            out.resize(size << 1);
        return size;
    }

    /** 获取应用程序路径
     *
     * @param out 输出对象
     * @return 路径长度
     */
    static inline size_t getAppPath(klib::dstring_t<256>& out) {
        size_t app_len = getAppName(out);
        char *p = out.data() + app_len, *begin = out.data();
        // 后向前循环，直到结束或者找到'\\'字符
        while (p >= begin && *p != '\\') --p;
        // 找到字符
        if (p >= begin) {
            *p = '\0';
            return p - begin;
        }
        // 未找到，返回0长度
        return 0;
    }

    /** 将相对路径格式化成基于当前程序路径的绝对路径
     *
     * @param out 输出对象
     * @param path 相对路径
     * @return 新的绝对路径的长度
     */
    static inline size_t absPathFromApp(klib::dstring_t<256>& out, const std::string_view& path) {
        size_t plen = getAppPath(out), all_len = plen + path.length();
        if (path[0] != '\\') ++all_len;
        // 如果缓冲区长度不足，进行扩充
        if (all_len >= out.size()) out.resize(all_len + 1);
        char *pos = out.data() + plen;
        if (path[0] != '\\') *pos++ = '\\';
        std::memcpy(pos, path.begin(), path.length());
        // 结尾补上'\0'字符
        out[all_len] = '\0';
        return all_len;
    }

} // namespace kwin
